<?php
/**
 * Created by User: wene<china_wangyu@aliyun.com> Date: 2019/4/11 Time: 14:54
 */

namespace think\restful\command;

use think\restful\curl\Curl;
use think\restful\validate\Api;
use think\restful\validate\Host;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\input\Argument;
use think\console\Output;
use think\restful\exception\ApiException;
use think\restful\helper\Helper;

/**
 * Class Check 自检API接口（采用的Curl/Curl）
 * @package think\restful\command
 */
class Check extends Command
{
    protected $config;
    protected $path;
    protected $data;
    protected $host;

    public function __construct($name = null)
    {
        parent::__construct($name);
        $this->config = config('api.');
    }

    /**
     * 命令行配置文件
     */
    protected function configure()
    {
        $this->setName('api:check')
            ->addOption('name', 'N', Option::VALUE_REQUIRED, '文档名称','API自检文档')
            ->addOption('host', 'H', Option::VALUE_REQUIRED, '验证API,网址：默认空，设置此属性，就不在读取配置值','')
            ->setDescription('验证 API 并生成 API Debug 文档');
    }

    /**
     * 执行函数
     * @param \think\console\Input $input
     * @param \think\console\Output $output
     * @return int|void|null
     */
    protected function execute(Input $input, Output $output)
    {
        try{
            $options = $input->getOptions();
            $this->host = empty($options['host']) ? $this->config['API_HOST']: $options['host'];
            empty($this->host) && ApiException::exception('请加上·-h·属性设置 网址，
                                                                    或在api.php配置API_HOST=网址');
            $hostValidate = new Host();
            $res = $hostValidate->execute($this->host);
            !$res && ApiException::exception('请加上·-h·属性设置 网址，或在api.php配置API_HOST=网址');
            $this->data = Helper::getApiVersionReflexData($this->config);
            $this->path = env('ROOT_PATH').DIRECTORY_SEPARATOR.$options['name'].date('Y-m-d H').'.md';
            $this->toCheck();
            $this->output->writeln(" API markdown 自检文档地址: ".$this->path);
        }catch (\Exception $exception){
            $this->output->writeln(" 执行命令失败。".$exception->getMessage());
        }
    }

    // 开始检验
    private function toCheck():void {
        $this->toMarkdownToc();
        $this->toCheckApi();
    }

    // 检验脚本文档TOC
    private function toMarkdownToc():void {
        Helper::toMarkdownToc($this->data,$this->path);
    }

    // 开始检验API
    private function toCheckApi():void {
        $fileContent = '';
        foreach ($this->data as $versionkey => $versionData){
            $fileContent .= '# '.Helper::cleanText($versionkey).PHP_EOL.PHP_EOL;
            foreach ($versionData as $objectKey => $objects){
                $fileContent .= $this->toCheckClass($objects['object']);
                $fileContent .= $this->toCheckAction($objects['methods'],$objectKey);
            }
        }
        Helper::write($this->path,$fileContent);
    }

    // 输出API接口类
    private function toCheckClass(array $objectData = []):?string {
        return Helper::toMarkdownClass($objectData);
    }

    // 检验接口
    private function toCheckAction(array $actionsData):?string {
        $fileContent = '';
        if(!empty($actionsData)) {
            $apiValidate = new Api();
            foreach ($actionsData as $actionKey => $actionData) {
                $fileContent .='### '.Helper::cleanText($actionKey.$actionData['doc']['value']).
                    PHP_EOL.PHP_EOL;
                $actionParamData = $this->getActionDefaultParam($actionData['param']);
                $curl = $apiValidate->execute($this->host.$actionData['route']['route'],
                    $actionData['route']['method'],$actionParamData);
                $fileContent .= $this->getActionCurlResult($curl);
            }
        }
        return $fileContent;
    }

    // 获取默认参数
    private function getActionDefaultParam(array $actionParamData = []):?array {
        if(empty($actionParamData)) return [];
        $params = [];
        foreach ($actionParamData as $paramDatum){
            if (empty($paramDatum['default'])) continue;
            $params[$paramDatum['name']] = $paramDatum['default'];
        }
        return $params;
    }

    private function getActionCurlResult(Curl $curl):?string {
        $fileContent = '`[validate status]` '.PHP_EOL.PHP_EOL;
        $fileContent .= ($curl->curl_error_code != 0 ? '异常':'正常').PHP_EOL.PHP_EOL;
        $fileContent .= '`[validate result]` '.PHP_EOL.PHP_EOL;
        $fileContent .= '```json'.PHP_EOL;
        if ($curl->error_code != 0){
            $fileContent .= '{'.PHP_EOL;
            $fileContent .= '    "responseCode":"500",'.PHP_EOL;
            $fileContent .= '    "responseCode":"设置的请求网址无法访问，网址：'.$this->host.'",'.PHP_EOL;
            $fileContent .= '    "responseData":{'.PHP_EOL;
            $fileContent .= '        "curl_error_msg":"'.$curl->error_message.'"'.PHP_EOL;
            $fileContent .= '    }'.PHP_EOL;
            $fileContent .= '}'.PHP_EOL;
        }else{
            $fileContent .= $curl->response.PHP_EOL;
        }
        $fileContent .= '```'.PHP_EOL.PHP_EOL;
        return $fileContent;
    }
}